#ifndef E76703F2_B2B7_4B49_808B_D0D9EE1C1C63
#define E76703F2_B2B7_4B49_808B_D0D9EE1C1C63

#include <sys/epoll.h>
#include <memory>
#include <functional>
#include <unordered_map>
#include <string>
#include <error.h>
#include "Sock.hpp"
#include "epoller.hpp"
#include "Comm.hpp"

class Connection;
class TcpServer;

using func_t = std::function<void(std::weak_ptr<Connection>)>;

const int num = 64;
const int EVENTIN = (EPOLLIN | EPOLLET);
const int EVENTOUT = (EPOLLOUT | EPOLLET);

class Connection
{
public:
	Connection(int sock) : sock_(sock)
	{
	}
	void setHandler(func_t recv_cb, func_t send_cb, func_t except_cb)
	{
		recv_cb_ = recv_cb;
		send_cb_ = send_cb;
		except_cb_ = except_cb;
	}
	void setSvr(std::shared_ptr<TcpServer> t)
	{
		svr = t;
	}
	~Connection()
	{
	}

private:
	int sock_;

	std::string inbuff;
	std::string outbuff;

public:
	func_t recv_cb_; // 可以封装，但是比较麻烦
	func_t send_cb_;
	func_t except_cb_;
	std::string ip;
	uint16_t port;
	std::shared_ptr<TcpServer> svr; /// 回调
};

class TcpServer : public std::enable_shared_from_this<TcpServer> , public nocopy   // 继承enable为了为当前对象this提供对应的shared_ptr
{
public:
	TcpServer(uint16_t port) : port_(port), listensock_ptr_(new Sock()), epoller_ptr_(new epoller())
	{
	}
	void Init()
	{
		listensock_ptr_->Socket();
		setNonBlock(listensock_ptr_->Fd()); /// 将sockfd转为非阻塞轮询
		listensock_ptr_->Bind(port_);
		listensock_ptr_->Listen();
		lg(Info, "listensock create and listen success");
		AddConnection(listensock_ptr_->Fd(), bind(&TcpServer::Accepter, this, std::placeholders::_1), nullptr, nullptr);
	}
	void Accepter(std::weak_ptr<Connection> con)
	{
		while (true)
		{
			struct sockaddr_in client;
			socklen_t len = sizeof(client);
			int sock = ::accept(listensock_ptr_->Fd(), (sockaddr *)&client, &len);
			if(sock > 0)
			{
				std::string clientip = inet_ntoa(client.sin_addr);
				uint16_t port = ntohs(client.sin_port);
				setNonBlock(sock);

			}
			else
			{
				if(errno == EWOULDBLOCK) break;
				if(errno == EINTR) continue;
				lg(Warnning, "accept error,errno:%d,errstring:%s", errno, strerror(errno));
				return;
			}
		}
	}
	void Recver(std::weak_ptr<Connection> con)
	{
	}

	void Sender(std::weak_ptr<Connection> con)
	{ /// 发送不是每次都要关心的，要做特殊处理
	
	}

	void Excepter(std::weak_ptr<Connection> con)
	{

	}

	void AddConnection(int sock, func_t recv_cb, func_t send_cb, func_t except_cb,const std::string& ip = "0.0.0.0",uint16_t port = 0) // 添加进入哈希表
	{
		std::shared_ptr<Connection> con(new Connection(sock));
		con->setHandler(recv_cb,send_cb,except_cb);
		con->setSvr(shared_from_this());
		con->ip = ip;
		con->port = port;
		//添加进入哈希表
		connections_.insert(std::make_pair(sock,con));
		//将对应的事件加入内核当中
		epoller_ptr_->EpollerUpdate(EPOLL_CTL_ADD,sock,EVENTIN);
	}
	bool isconnectsafe(int sock)
	{
		if(connections_.count(sock)) return true;
		return false;
	}
	void Dispatcher(int timeout) // 派发任务
	{
		int n = epoller_ptr_->EpollerWait(resv, num, timeout);
		if (n > 0)
		{
			for (int i = 0; i < n; i++)
			{
				int events = resv[i].events;
				int sock = resv[i].data.fd;
				if (events & EPOLLERR)
				{ // 对异常情况统一给读写处理
					events |= (EPOLLIN | EPOLLOUT);
				}
				if (events & EPOLLHUP)
				{
					events |= (EPOLLIN | EPOLLOUT);
				}
				if (events & EPOLLIN)
				{
					connections_[sock]->recv_cb_(connections_[sock]);
				}
				if (events & EPOLLOUT)
				{
					connections_[sock]->send_cb_(connections_[sock]);
				}
			}
		}
		else if (n == 0)
		{
			std::cout << "time out" << std::endl;
		}
		else
		{
			lg(Warnning, "epolle_wait error,errno : %d,errstring : %s", errno, strerror(errno));
		}
	}
	void loop()
	{
		// epoller_ptr_->EpollerUpdate(EPOLL_CTL_ADD,listensock_ptr_->Fd(),EVENTIN);
		while (true)
		{
			Dispatcher(1000);
		}
	}
	~TcpServer()
	{
	}

private:
	uint16_t port_;
	std::shared_ptr<Sock> listensock_ptr_;
	std::shared_ptr<epoller> epoller_ptr_;
	std::unordered_map<int, std::shared_ptr<Connection>> connections_;
	struct epoll_event resv[num];
	// bool quit ; // 只能进行一次loop --- 不对
};

#endif /* E76703F2_B2B7_4B49_808B_D0D9EE1C1C63 */
